package confidence;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import confidence.tools.*;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

/**
 * 置信度计算
 */
public class Confidence {

    /**
     * 默认获取融合置信度
     * @param jsonObject
     * @param normal_type
     * @return
     */
    public static ConfidenceInfo confidence_level(JSONObject jsonObject, String normal_type) {
        if (StringUtils.isBlank(normal_type)) {
            normal_type = "fusionRes";
        }
        JSONObject resultObj = jsonObject.getJSONObject("result");
        String normal_aoi = parseValueFromJsonArray(normal_type, resultObj, "_4D");
        String init_aoi = parseValueFromJsonArray("queryRes", resultObj, "_4D");
        ConfidenceType confidenceType = aoi_confidence(normal_aoi, init_aoi, 0.85f);
        if (! (0 == confidenceType.getType())) {
            return ConfidenceInfo.builder().level("高").scoreType(confidenceType.getType()).score(confidenceType.getScore()).reason("初始积分").build();
        } else {
//            主道路
            String normal_road = parseValueFromJsonArray(normal_type, resultObj, "_4E-1");
            String init_road = parseValueFromJsonArray("queryRes", resultObj, "_4E-1");
//            主门牌
            String normal_num = parseValueFromJsonArray(normal_type, resultObj, "_5A-1");
            String init_num = parseValueFromJsonArray("queryRes", resultObj, "_5A-1");

            int road_num_value = road_num_confidence(normal_road, normal_num, init_road, init_num);
            if (1 == road_num_value) {
                return ConfidenceInfo.builder().level("高").scoreType(0).score(1f).reason("道路门牌").build();
            } else {
                int poi_value = poi_confidence(normal_aoi, init_aoi);
                if (1 == poi_value) {
                    return ConfidenceInfo.builder().level("高").scoreType(0).score(1f).reason("poi名称").build();
                } else {
                    String normal_floor = parseValueFromJsonArray(normal_type, resultObj, "_5C");
                    String query_floor = parseValueFromJsonArray("queryRes", resultObj, "_5C");

                    String normal_village = parseValueFromJsonArray(normal_type, resultObj, "_4B");
                    String normal_group = parseValueFromJsonArray(normal_type, resultObj, "_4C");

                    String normal_town = parseValueFromJsonArray(normal_type, resultObj, "_4A");
                    String query_town = parseValueFromJsonArray("queryRes", resultObj, "_4A");

                    int condition_value = condition_confidence(normal_aoi, init_aoi, normal_floor, query_floor, normal_village,
                            normal_group, normal_town, query_town);
                    if (1 == condition_value) {
                        return ConfidenceInfo.builder().level("高").scoreType(0).score(1f).reason("条件计算").build();
                    } else {
//                        计算中置信度
                        ConfidenceType middle = aoi_confidence(normal_aoi, init_aoi, 0.6f);
                        if (0 != middle.getType()) {
                            return ConfidenceInfo.builder().level("中").scoreType(middle.getType()).score(middle.getScore()).reason("小区/AOI").build();
                        } else {
                            int contain = condition_contain(normal_aoi, init_aoi);
                            if (1 == contain) {
                                return ConfidenceInfo.builder().level("中").scoreType(0).score(1).reason("包含关系").build();
                            } else {
                                return ConfidenceInfo.builder().level("低").scoreType(0).score(0).reason("").build();
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 中置信度，原始包含清洗
     */
    private static int condition_contain(String normal_aoi, String init_aoi) {
        String normal_convert = StringConvertUtil.formatText(normal_aoi);
        String init_convert = StringConvertUtil.formatText(init_aoi);
        if(StringUtils.isBlank(normal_convert) || StringUtils.isBlank(init_convert)) {
            return 0;
        }
        if (init_convert.contains(normal_convert)) {
            return 1;
        }
        return 0;
    }

    /**
     * 条件置信度
     */
    private static int condition_confidence(String normal_aoi, String init_aoi, String normal_floor, String init_floor,
                                            String normal_village, String normal_group, String normal_town, String init_town){
        if (StringUtils.isBlank(normal_aoi) || StringUtils.isBlank(init_aoi)) {
            return 0;
        }

        String convert_normal = StringConvertUtil.formatText(normal_aoi);
        String convert_init = StringConvertUtil.formatText(init_aoi);

//        相同字符长度
        int same_char_len = CommonUtil.same_char(convert_normal, convert_init).length;
        boolean is_euqal = number_equal(convert_normal, convert_init);
//        去除分类词后的长度
        int length = ClassifierWord.trimClassifierWord(normal_aoi).length();
        boolean floor_equal = floor(normal_floor, init_floor);

        if (same_char_len >=3 && is_euqal && length > 0 && floor_equal) {
            return 1;
        } else {
            if( (normal_village.contains("村委会") || StringUtils.isNotBlank(normal_group)) && normal_town.equals(init_town) ) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    private static boolean floor(String normal_floor, String init_floor) {
        if (StringUtils.isBlank(normal_floor)) {
            return false;
        }
        return number_equal(normal_floor, init_floor);
    }

    /**
     *
     */
    private static boolean number_equal(String convert_normal, String convert_init) {
        String number_normal = CommonUtil.getChineseNumber(convert_normal);
        String number_init = CommonUtil.getChineseNumber(convert_init);
        if (StringUtils.isNotBlank(number_normal) && StringUtils.isNotBlank(number_init) &&
            number_normal.equals(number_init)) {
            return true;
        }
        return false;
    }

    /**
     * poi 置信度
     */
    private static int poi_confidence(String normal_aoi, String init_aoi) {
        if(StringUtils.isBlank(normal_aoi) || StringUtils.isBlank(init_aoi)) {
            return 0;
        }
        String con_normal = StringConvertUtil.formatText(normal_aoi);
        String con_init = StringConvertUtil.formatText(init_aoi);
        if (con_normal.equals(con_init)) {
            return 1;
        } else {
            return 0;
        }
    }



    /**
     * # 道路，门牌置信度
     * @param normal_road
     * @param normal_num
     * @param init_road
     * @param init_num
     * @return
     */
    private static int road_num_confidence(String normal_road, String normal_num, String init_road, String init_num) {
        if (StringUtils.isBlank(normal_road) || StringUtils.isBlank(normal_num) ||
            StringUtils.isBlank(init_road) || StringUtils.isBlank(init_num)) {
            return 0;
        }

        if (FormatRoad.format_road_name(normal_road).equals(FormatRoad.format_road_name(init_road)) &&
           FormatRoad.format_road_num(normal_num).equals(FormatRoad.format_road_num(init_num))) {
            return 1;
        }

        return 0;
    }


    /**
     * 计算置信度得分和类型
     * @param normal_aoi
     * @param init_aoi
     * @param level
     * @return
     */
    private static ConfidenceType aoi_confidence(String normal_aoi, String init_aoi, float level) {
        if(StringUtils.isBlank(normal_aoi) || StringUtils.isBlank(init_aoi)) {
            return ConfidenceType.builder().type(0).score(0.0f).build();
        }

        String con_normal = StringConvertUtil.formatText(normal_aoi); //todo
        String con_init = StringConvertUtil.formatText(init_aoi); //todo
        char[] same_char = CommonUtil.same_char(con_normal, con_init);
        int same_char_len = same_char.length;
        float score = (2 * same_char_len) / (con_normal.length() + con_init.length());
        if (Float.compare(score, level) >=0) {
//            未修复
            return ConfidenceType.builder().type(1).score(score).build();
        } else {
//            形近字识别
//            字符串抠出相同的部分
            char[] normal_remain = CommonUtil.diff_char(con_normal, same_char);
            char[] init_remain = CommonUtil.diff_char(con_init, same_char);

            String normal_remain_repair = WrongWordRepair.repair(normal_remain);
            String init_remain_repair = WrongWordRepair.repair(init_remain);
            char[] repair_same_list = CommonUtil.same_char(normal_remain_repair, init_remain_repair);
            int repair_same_list_len = repair_same_list.length;
            score = (2 * (same_char_len + (repair_same_list_len / 2))) / (con_normal.length() + con_init.length());
            if (Float.compare(score, level) >=0) {
//                经过形近字修复
                return ConfidenceType.builder().type(2).score(score).build();
            } else {
                char[] normal = CommonUtil.diff_char(normal_remain_repair, repair_same_list);
                char[] init = CommonUtil.diff_char(init_remain_repair, repair_same_list);
                int same_pinyin_len = PinyinRepair.samePinyin(new String(normal), new String(init));
                score = (2 * (same_char_len + (repair_same_list_len + same_pinyin_len) / 2)) / (
                        con_normal.length() + con_init.length());
                if (Float.compare(score, level) >=0) {
//                    经过形近字和拼音修复
                    return ConfidenceType.builder().type(3).score(score).build();
                } else {
                    return ConfidenceType.builder().type(0).score(score).build();
                }
            }
        }
    }

    public static String parseValueFromJsonArray(String jsonKey, JSONObject resultObj, String endWith) {
        try {
            JSONArray jsonArray = resultObj.getJSONArray(jsonKey);
            for(int i=0; i<jsonArray.size(); i++) {
                String item = jsonArray.getString(i);
                if (item.endsWith(endWith)) {
                    return item.replaceFirst(endWith, "");
                }
            }
            return "";
        } catch (Exception e) {
            return "";
        }
    }

    @Builder
    @Data
    public static class ConfidenceInfo {
        //置信度级别
        private String level;
        //置信度得分类型
        private int scoreType;
        //置信度得分
        private float score;
        //置信度原因
        private String reason;

        @Override
        public String toString() {
            return "ConfidenceInfo{" +
                    "level='" + level + '\'' +
                    ", type=" + scoreType +
                    ", score=" + score +
                    ", reason='" + reason + '\'' +
                    '}';
        }
    }

    @Builder
    @Data
    private static class ConfidenceType{
        /**
         * 置信度类型
         * 0: 未知
         * 1: 初始积分
         * 2: 形近字修复
         * 3: 形近字与拼音修复
         */
        private int type;
        //置信度得分
        private float score;

        @Override
        public String toString() {
            return "ConfidenceType{" +
                    "type=" + type +
                    ", score=" + score +
                    '}';
        }
    }
}
